/*
 * C.cxx
 *
 *  Created on: 3:51:45 PM Oct 14, 2012
 *  Author: Pallab
 *
 * "I have not failed, I have just found 10000 ways that won't work.
*/

#include <iostream>
#include <algorithm>
#include <vector>
#include <sstream>
#include <fstream>
#include <string>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <functional>
#include <bitset>
#include <iomanip>

#include <ctime>
#include <cassert>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <climits>
#include <cstring>
#include <cstdlib>

using namespace std;

#define foR(i1,st,ed) for(int i1 = st , j1 = ed ; i1 < j1 ; ++i1 )
#define fo(i1,ed) foR( i1 , 0 , ed )
#define foE(i1,st,ed) foR( i1, st, ed+1 )
#define foit(i, x) for (typeof((x).begin()) i = (x).begin(); i != (x).end(); i++)
#define bip system("pause")
#define Int long long
#define pb push_back
#define SZ(X) (int)(X).size()
#define LN(X) (int)(X).length()
#define mk make_pair
#define SET( ARRAY , VALUE ) memset( ARRAY , VALUE , sizeof(ARRAY) )
#define line puts("")

inline void wait(double seconds) {
	double endtime = clock() + (seconds * CLOCKS_PER_SEC);
	while (clock() < endtime) {
		;
	}
}
#define T int
inline T fastIn() {
	register char c = 0;
	register T a = 0;
	while (c < 33)
		c = getchar();
	while (c > 33) {
		a = (a * 10) + (c - '0');
		c = getchar();
	}
	return a;
}
string s1, s2;
//split a string
inline vector<string> parse(string mystr) {
	char *sentence = (char*) mystr.c_str(); // string to chat array
	char *word;
	static char delim[] = ",}{";
	vector<string> words;
	for (word = strtok(sentence, delim); word; word = strtok(0, delim)) {
		if (strlen(word)) {
			if (word[0] == '{' || word[0] == '}')
				continue;
			words.pb(word);
		}
	}
	return words;
}
inline vector<string> parse3(string mystr) {
	char *sentence = (char*) mystr.c_str(); // string to chat array
	char *word;
	static char delim[] = ":";
	vector<string> words;
	for (word = strtok(sentence, delim); word; word = strtok(0, delim)) {
		if (strlen(word)) {
			words.pb(word);
		}
	}
	return words;
}
inline pair<string, string> parse2(string ss) {
	vector<string> vi = parse3(ss);
	return mk(vi[0], vi[1]);
}
inline void read() {
	getline(cin, s1);
	getline(cin, s2);
}
map<string, string> old_dic, new_dic;
inline void proc() {
	old_dic.clear(), new_dic.clear();

	vector<string> dic1 = parse(s1);
	vector<string> dic2 = parse(s2);
	fo(i,SZ(dic1)) {
		pair<string, string> tmp = parse2(dic1[i]);
		old_dic[tmp.first] = tmp.second;
	}
	fo(i,SZ(dic2))
	{
		pair<string, string> tmp = parse2(dic2[i]);
		new_dic[tmp.first] = tmp.second;
	}
	vector<string> added,
deleted
,changed	;
	//notun kon gula add hoche
	foit(it, new_dic)
	{
		string key = it->first;
		if (old_dic.count(key) < 1)
			added.pb(key);
	}
	//ge gula bad giche
	foit( it, old_dic)
	{
		string key = it->first;
		if (new_dic.count(key) < 1)
			deleted.pb(key);
	}

	//ge gula change hoiche
	foit(it, old_dic)
	{
		string key = it->first;
		if (new_dic.count(key))
			if (it->second != new_dic[key])
				changed.pb(key);
	}
	bool flag = false;
	if (SZ(added)) {
		flag |= true;
		cout << "+";
		fo(i,SZ(added))
		{
			if (i)
				cout << ',';
			cout << added[i];
		}
		line;
	}
	if (SZ(deleted)) {
		flag |= true;
		cout << "-";
		fo(i,SZ(deleted))
		{
			if (i)
				cout << ',';
			cout << deleted[i];
		}
		line;
	}
	if (SZ(changed)) {
		flag |= true;
		cout << "*";
		fo(i,SZ(changed))
		{
			if (i)
				cout << ',';
			cout << changed[i];
		}
		line;
	}
	if (!flag)
		puts("No changes");
	line;
}
int main() {
	int kase = 1;
#if defined( xerxes_pc )
	if (!freopen("C/in1", "r", stdin))
		puts("error opening file C/in1 "), assert(0);
	kase = 1;
#endif
	scanf("%d\n", &kase);
	fo(i,kase)
	{
		read();
		proc();
	}
	return 0;
}

